package com.zhtkj.scheduler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import com.zhtkj.constant.AccessData;
import com.zhtkj.constant.CarConstant;
import com.zhtkj.constant.CardConstant;
import com.zhtkj.constant.Constant;
import com.zhtkj.constant.FenceConstant;
import com.zhtkj.dto.CarAnalysis;
import com.zhtkj.entity.gateway.CarEvent;
import com.zhtkj.entity.mongo.CarHistory;
import com.zhtkj.entity.zhatu.AutoAnalysisdata;
import com.zhtkj.entity.zhatu.Car;
import com.zhtkj.entity.zhatu.Card;
import com.zhtkj.entity.zhatu.Consapp;
import com.zhtkj.entity.zhatu.Gpsfence;
import com.zhtkj.entity.zhatu.TransportEnterprises;
import com.zhtkj.entity.zhatu.UnloadingArea;
import com.zhtkj.mapper.gateway.CarEventMapper;
import com.zhtkj.mapper.zhatu.AutoAnalysisdataMapper;
import com.zhtkj.mapper.zhatu.CarMapper;
import com.zhtkj.mapper.zhatu.CardMapper;
import com.zhtkj.mapper.zhatu.ConsappMapper;
import com.zhtkj.mapper.zhatu.GpsfenceMapper;
import com.zhtkj.mapper.zhatu.TransportEnterprisesMapper;
import com.zhtkj.mapper.zhatu.UnloadingAreaMapper;
import com.zhtkj.service.AnalysisService;
import com.zhtkj.ui.Launcher;
import com.zhtkj.util.Point;

/** 
* @ClassName: TargetScheduler 
* @Description: 定时任务，分析违规、趟次等等 
* @author mafeng 
* @date 2017年9月7日 上午9:45:15 
*  
*/
@Component("targetScheduler")
public class TargetScheduler {

	private static Logger logger = Logger.getLogger(TargetScheduler.class);
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	@Autowired
	private AnalysisService analysisService;
	
	@Autowired
	private GpsfenceMapper gpsfenceMapper;
	
	@Autowired
	private CarEventMapper carEventMapper;
	
	@Autowired
	private ConsappMapper consappMapper;
	
	@Autowired
	private UnloadingAreaMapper unloadingAreaMapper;
	
	@Autowired
	private CarMapper carMapper;
	
	@Autowired
	private CardMapper cardMapper;
	
	@Autowired
	private TransportEnterprisesMapper transportEnterprisesMapper;
	
	
	@Autowired
	private AutoAnalysisdataMapper autoAnalysisdataMapper;
	
	//作弊分析方法读取数据（执行配置在springContext.xml文件里面）
	public void pullHistoryData() {
		AccessData accessData = null;
		//读取围栏、核准证等数据
		try {
			accessData = this.pullFenceData();
		} catch (Exception e) {
			logger.error(e, e);
			Launcher.setText("程序发生异常：" + e.getStackTrace());
			e.printStackTrace();
		}
		
		//从mongodb数据库读取待分析的数据(数据量太大必须分2次查询，不然会报内存溢出)
		DateTime now = DateTime.now();
		Date startTime = null;
		Date endTime = null;
		if (now.getMinuteOfHour() > 0 && now.getMinuteOfHour() < 15) {
			startTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.minusHours(1).toString("yyyy-MM-dd HH:45:00")).toDate();
			endTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:00:00")).toDate();
		} else if (now.getMinuteOfHour() > 15 && now.getMinuteOfHour() < 30) {
			startTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:00:00")).toDate();
			endTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:15:00")).toDate();
		} else if (now.getMinuteOfHour() > 30 && now.getMinuteOfHour() < 45) {
			startTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:15:00")).toDate();
			endTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:30:00")).toDate();
		} else if (now.getMinuteOfHour() > 45 && now.getMinuteOfHour() < 59) {
			startTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:30:00")).toDate();
			endTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(now.toString("yyyy-MM-dd HH:45:00")).toDate();
		}

		//将待分析的数据放到分析对象上面
		Query query = new Query();
		query.addCriteria(Criteria.where("receiveTime").gte(startTime.getTime()).lt(endTime.getTime())).with(new Sort(Direction.ASC, "receiveTime"));
		Launcher.setText("数据库读取数据开始：" + DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
		List<CarHistory> carHistorys = mongoTemplate.find(query, CarHistory.class, "zt_car_history_" + new DateTime(startTime).getMonthOfYear());
		Launcher.setText("数据库读取数据结束：" + DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
		Launcher.setText("本次分析从数据库读取了：" + carHistorys.size() + "条数据");
		for (CarHistory carHistory: carHistorys) {
			if (carHistory.getCarNumber() != null && !carHistory.getCarNumber().equals("") &&
					accessData.getCarConstant().getCarMap().get(carHistory.getCarNumber()) != null) {
				CarAnalysis carAnalysis = Constant.constantMap.get(carHistory.getCarNumber());
				if (carAnalysis != null) {
					carAnalysis.getCarHistoryList().add(carHistory);
				} else {
					carAnalysis = new CarAnalysis();
					carAnalysis.getCarHistoryList().add(carHistory);
					Constant.constantMap.put(carHistory.getCarNumber(), carAnalysis);
				}
			}
		}
		
		//设置车牌和sim卡
		for (CarAnalysis carAnalysis: Constant.constantMap.values()) {
			if (carAnalysis.getCarHistoryList().size() > 0) {
				carAnalysis.setCarNumber(carAnalysis.getCarHistoryList().get(0).getCarNumber());
				carAnalysis.setDevPhone(carAnalysis.getCarHistoryList().get(0).getDevPhone());
			}
		}
		//删除没有报数据的对象
		Iterator<Map.Entry<String, CarAnalysis>> it = Constant.constantMap.entrySet().iterator();  
        while (it.hasNext()) {  
            Map.Entry<String, CarAnalysis> entry = it.next();  
            if (entry.getValue().getCarHistoryList().size() == 0) {  
                it.remove();  
            }  
        }
		
		//开始分析本次读取的数据
		Launcher.setText("开始分析：" + DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
		for (CarAnalysis carAnalysis: Constant.constantMap.values()) {
			try {
				analysisService.overSpeedAnalysis(accessData, carAnalysis);
				analysisService.moveAndNoSpeedAnalysis(accessData, carAnalysis);
				analysisService.speedAndNoMoveAnalysis(accessData, carAnalysis);
				analysisService.inRestrictAreaAnalysis(accessData, carAnalysis);
				analysisService.illegalBucketAnalysis(accessData, carAnalysis);
				analysisService.illegalWorkAnalysis(accessData, carAnalysis);
				analysisService.boxStateAnalysis(accessData, carAnalysis);
				// 趟次分析，济南暂时不用
				/*tripService.tripAnalysis(accessData, carAnalysis);*/
			} catch (Exception e) {
				logger.error("", e);
				e.printStackTrace();
			}
		}
		
		//将每辆车的最后一条CarHistory缓存并将carHistoryList数据清空
		for (CarAnalysis carAnalysis: Constant.constantMap.values()) {
			if (carAnalysis.getCarHistoryList().size() > 0) {
				carAnalysis.setLastCarHistory(carAnalysis.getCarHistoryList().get(carAnalysis.getCarHistoryList().size() - 1));
			}
			carAnalysis.setCarHistoryList(new ArrayList<CarHistory>());
		}
		
		//从事件表搬运一些违规事件
		try {
			this.portageEvent(accessData, new DateTime(startTime).getMonthOfYear(), new DateTime(startTime).toString("yyyy-MM-dd HH:mm:ss"), new DateTime(endTime).toString("yyyy-MM-dd HH:mm:ss"));
		} catch (Exception e) {
			logger.error("", e);
			e.printStackTrace();
		}
		
		//清空本分析产生的一些临时数据以释放内存
		carHistorys.clear();
		accessData.clearData();
		
		Launcher.setText("结束分析：" + DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
		
		System.gc();
	}
	
	private AccessData pullFenceData() {
		AccessData accessData = new AccessData();
		
		CarConstant carConstant = new CarConstant();
    	List<Car> cars = carMapper.selectAll();
    	List<TransportEnterprises> enterprises = transportEnterprisesMapper.selectAll();
    	for (Car car: cars) {
			carConstant.getCarMap().put(car.getNumberPlate(), car.getCarId());
			for (TransportEnterprises enterprise: enterprises) {
				if (car.getEnterpriseId().intValue() == enterprise.getEnterpriseId()) {
					carConstant.getCarEnterpriseMap().put(car.getNumberPlate(), enterprise.getEnterpriseId().longValue());
					carConstant.getCarEnterpriseNameMap().put(car.getNumberPlate(), enterprise.getEnterpriseAbbreviation());
				}
			}
    	}
    	accessData.setCarConstant(carConstant);
    	
    	// 卸区围栏id、卸区id对应Map(后面用的到)
    	Map<Long, Long> unloadingToFence = new HashMap<Long, Long>();
    	
    	
    	FenceConstant fenceConstant = new FenceConstant();
		//查询有效期内的工地电子围栏
		List<Consapp> consapps = consappMapper.selectValidConsapp(DateTime.now().toString("yyyy-MM-dd"));
		for (Consapp consapp: consapps) {
			if (consapp.getGpsfence() != null && !consapp.getGpsfence().equals("")) {
				List<Point> polygon = new ArrayList<Point>();
				String[] poiStr = consapp.getGpsfence().split(";");
				for (String poi: poiStr) {
					Point point = new Point(Double.parseDouble(poi.split(",")[0]), Double.parseDouble(poi.split(",")[1]));
					polygon.add(point);
				}
				fenceConstant.getConsappMap().put(consapp.getFenceId(), polygon);
				fenceConstant.getConsappInfoMap().put(consapp.getConsappId(), polygon);
				unloadingToFence.put(consapp.getFenceId(), consapp.getConsappId());
			}
		}
		
		//查询有效期内的卸区电子围栏
		List<UnloadingArea> unloadingAreas = unloadingAreaMapper.selectValidUnloadingArea(DateTime.now().toString("yyyy-MM-dd"));
		for (UnloadingArea unloadingArea: unloadingAreas) {
			if (unloadingArea.getGpsfence() != null && !unloadingArea.getGpsfence().equals("")) {
				List<Point> polygon = new ArrayList<Point>();
				String[] poiStr = unloadingArea.getGpsfence().split(";");
				for (String poi: poiStr) {
					Point point = new Point(Double.parseDouble(poi.split(",")[0]), Double.parseDouble(poi.split(",")[1]));
					polygon.add(point);
				}
				fenceConstant.getUnloadingMap().put(unloadingArea.getFenceId(), polygon);
				fenceConstant.getUnloadingInfoMap().put(unloadingArea.getUnloadingId(), polygon);
			}
		}
		
		//查询路线围栏数据
		Gpsfence query = new Gpsfence();
		query.setFenceType(1);
		List<Gpsfence> lines = gpsfenceMapper.select(query);
		for (Gpsfence gpsfence: lines) {
			List<Point> polygon = new ArrayList<Point>();
			String[] poiStr = gpsfence.getFencePos().split(";");
			for (String poi: poiStr) {
				Point point = new Point(Double.parseDouble(poi.split(",")[0]), Double.parseDouble(poi.split(",")[1]));
				polygon.add(point);
			}
			fenceConstant.getLineMap().put(gpsfence.getFenceId(), polygon);
		}
		
		//查询禁区围栏数据
		query = new Gpsfence();
		query.setFenceType(6);
		List<Gpsfence> restricts = gpsfenceMapper.select(query);
		for (Gpsfence gpsfence: restricts) {
			List<Point> polygon = new ArrayList<Point>();
			String[] poiStr = gpsfence.getFencePos().split(";");
			for (String poi: poiStr) {
				Point point = new Point(Double.parseDouble(poi.split(",")[0]), Double.parseDouble(poi.split(",")[1]));
				polygon.add(point);
			}
			fenceConstant.getRestrictMap().put(gpsfence.getFenceId(), polygon);
		}
		
		//查询停车场围栏数据
		query = new Gpsfence();
		query.setFenceType(5);
		List<Gpsfence> parkings = gpsfenceMapper.select(query);
		for (Gpsfence gpsfence: parkings) {
			List<Point> polygon = new ArrayList<Point>();
			String[] poiStr = gpsfence.getFencePos().split(";");
			for (String poi: poiStr) {
				Point point = new Point(Double.parseDouble(poi.split(",")[0]), Double.parseDouble(poi.split(",")[1]));
				polygon.add(point);
			}
			fenceConstant.getParkingMap().put(gpsfence.getFenceId(), polygon);
		}
		accessData.setFenceConstant(fenceConstant);
		
		//查询运输核准证
		CardConstant cardConstant = new CardConstant();
		List<Card> cards = cardMapper.selectCardByDate(DateTime.now().minusMinutes(30).toString("yyyy-MM-dd"));
	    for (Card card: cards) {
	    	//添加运输核准证到map
	    	cardConstant.getCardMap().put(card.getTranCarids(), card.getCardId());
	    	
	    	//添加核准证关联工地电子围栏id
	    	String consappFenceid = card.getConsappFenceid();
	    	if (consappFenceid != null) {
	    		if (consappFenceid.contains(",")) {
	    			String[] consappFences = consappFenceid.split(",");
		    		for (int i = 0; i < consappFences.length; i++) {
		    			if (cardConstant.getCarConsappMap().get(card.getTranCarids()) == null) {
		    				List<Long> consappFenceIds = new ArrayList<Long>();
		    				consappFenceIds.add(Long.parseLong(consappFences[i]));
		    				cardConstant.getCarConsappMap().put(card.getTranCarids(), consappFenceIds);
		    			} else {
		    				cardConstant.getCarConsappMap().get(card.getTranCarids()).add(Long.parseLong(consappFences[i]));
		    			}
		    		}
	    		} else {
	    			if (cardConstant.getCarConsappMap().get(card.getTranCarids()) == null) {
	    				List<Long> consappFenceIds = new ArrayList<Long>();
	    				consappFenceIds.add(Long.parseLong(consappFenceid));
	    				cardConstant.getCarConsappMap().put(card.getTranCarids(), consappFenceIds);
	    			} else {
	    				cardConstant.getCarConsappMap().get(card.getTranCarids()).add(Long.parseLong(consappFenceid));
	    			}
	    		}
	    	}
	    	
	    	//添加车辆关联工地的id集合
	    	Long consappId = card.getConsappId();
	    	if (cardConstant.getConsappIdMap().get(card.getTranCarids()) == null) {
	    		List<Long> consappIds = new ArrayList<Long>();
	    		consappIds.add(consappId);
				cardConstant.getConsappIdMap().put(card.getTranCarids(), consappIds);
	    	} else {
	    		cardConstant.getConsappIdMap().get(card.getTranCarids()).add(consappId);
	    	}
	    	
	    	//添加车辆关联卸区的id集合
	    	String unloadingFenceIdsStr = card.getUnloadingFenceid();
	    	if (cardConstant.getUnloadingIdMap().get(card.getTranCarids()) == null) {
	    		List<Long> unloadingIds = new ArrayList<Long>();
	    		List<String> unloadingFenceIdList = Arrays.asList(unloadingFenceIdsStr.split(","));
	    		for (String unloadingFenceId: unloadingFenceIdList) {
	    			if (unloadingToFence.get(Long.parseLong(unloadingFenceId)) != null) {
	    				unloadingIds.add(unloadingToFence.get(Long.parseLong(unloadingFenceId)));
	    			}
	    		}
				cardConstant.getConsappIdMap().put(card.getTranCarids(), unloadingIds);
	    	} else {
	    		List<String> unloadingFenceIdList = Arrays.asList(unloadingFenceIdsStr.split(","));
	    		for (String unloadingFenceId: unloadingFenceIdList) {
	    			if (unloadingToFence.get(Long.parseLong(unloadingFenceId)) != null) {
	    				cardConstant.getConsappIdMap().get(card.getTranCarids()).add(unloadingToFence.get(Long.parseLong(unloadingFenceId)));
	    			}
	    		}
	    	}
	    	
	    	//添加车辆关联的工地最早开工时间
	    	String licStarttime = card.getLicStarttime();
	    	String startKey = card.getTranCarids() + card.getConsappFenceid();//车牌号+工地围栏id为key
	    	if (licStarttime != null) {
	    		if (cardConstant.getEarlyWorkMap().get(startKey) != null) {
		    		if (licStarttime != null && Integer.parseInt(licStarttime) < cardConstant.getEarlyWorkMap().get(startKey)) {
		    			cardConstant.getEarlyWorkMap().put(startKey, Integer.parseInt(licStarttime));
		    		}
		    	} else {
		    		cardConstant.getEarlyWorkMap().put(startKey, Integer.parseInt(licStarttime));
		    	}
	    	}
	    	
	    	//添加核准证关联卸区电子围栏id
	    	String unloadingFenceid = card.getUnloadingFenceid();
	    	if (unloadingFenceid != null) {
	    		if (unloadingFenceid.contains(",")) {
	    			String[] unloadingFences = unloadingFenceid.split(",");
		    		for (int i = 0; i < unloadingFences.length; i++) {
		    			if (cardConstant.getCarUnloadingMap().get(card.getTranCarids()) == null) {
		    				List<Long> unloadingFenceIds = new ArrayList<Long>();
		    				unloadingFenceIds.add(Long.parseLong(unloadingFences[i]));
		    				cardConstant.getCarUnloadingMap().put(card.getTranCarids(), unloadingFenceIds);
		    			} else {
		    				cardConstant.getCarUnloadingMap().get(card.getTranCarids()).add(Long.parseLong(unloadingFences[i]));
		    			}
		    		}
	    		} else {
	    			if (cardConstant.getCarUnloadingMap().get(card.getTranCarids()) == null) {
	    				List<Long> unloadingFenceIds = new ArrayList<Long>();
	    				unloadingFenceIds.add(Long.parseLong(unloadingFenceid));
	    				cardConstant.getCarUnloadingMap().put(card.getTranCarids(), unloadingFenceIds);
	    			} else {
	    				cardConstant.getCarUnloadingMap().get(card.getTranCarids()).add(Long.parseLong(unloadingFenceid));
	    			}
	    		}
	    	}
	    	//添加车辆关联的工地最晚停工时间
	    	String licEndtime = card.getLicEndtime();
	    	String endKey = card.getTranCarids() + card.getUnloadingFenceid();//车牌号+卸区围栏id为key
	    	if (licEndtime != null) {
	    		if (cardConstant.getLatestWorkMap().get(endKey) != null) {
		    		if (Integer.parseInt(licEndtime) < cardConstant.getLatestWorkMap().get(endKey)) {
		    			cardConstant.getLatestWorkMap().put(endKey, Integer.parseInt(licEndtime));
		    		}
		    	} else {
		    		cardConstant.getLatestWorkMap().put(endKey, Integer.parseInt(licEndtime));
		    	}
	    	}
	    	
	    	//添加核准证关联路线电子围栏id
	    	String gpsroadid = card.getGpsroadid();
	    	if (gpsroadid != null) {
	    		if (gpsroadid.contains(",")) {
	    			String[] gpsroadFences = gpsroadid.split(",");
		    		for (int i = 0; i < gpsroadFences.length; i++) {
		    			if (cardConstant.getCarLineMap().get(card.getTranCarids()) == null) {
		    				List<Long> gpsroadFenceIds = new ArrayList<Long>();
		    				gpsroadFenceIds.add(Long.parseLong(gpsroadFences[i]));
		    				cardConstant.getCarLineMap().put(card.getTranCarids(), gpsroadFenceIds);
		    			} else {
		    				cardConstant.getCarLineMap().get(card.getTranCarids()).add(Long.parseLong(gpsroadFences[i]));
		    			}
		    		}
	    		} else {
	    			if (cardConstant.getCarLineMap().get(card.getTranCarids()) == null) {
	    				List<Long> gpsroadFenceIds = new ArrayList<Long>();
	    				gpsroadFenceIds.add(Long.parseLong(gpsroadid));
	    				cardConstant.getCarLineMap().put(card.getTranCarids(), gpsroadFenceIds);
	    			} else {
	    				cardConstant.getCarLineMap().get(card.getTranCarids()).add(Long.parseLong(gpsroadid));
	    			}
	    		}
	    	}
	    }
	    accessData.setCardConstant(cardConstant);
	    
	    return accessData;
	}
	
	//从事件表搬运一些事件
	private void portageEvent(AccessData accessData, Integer month, String startTime, String endTime) {
		List<CarEvent> carEvents = carEventMapper.selectByTypeAndTime(month, startTime, endTime);
		for (int i = 0; i < carEvents.size(); i++) {
			CarEvent carEvent = carEvents.get(i);
			if (accessData.getCarConstant().getCarMap().get(carEvent.getCarNumber()) != null) {
				continue;
			}
			AutoAnalysisdata autoAnalysisdata = new AutoAnalysisdata(carEvent.getCarNumber(), carEvent.getDevPhone());
			autoAnalysisdata.setGpsPosX(carEvent.getGpsPosX());
			autoAnalysisdata.setGpsPosY(carEvent.getGpsPosY());
			autoAnalysisdata.setGpsSpeed(carEvent.getGpsSpeed());
			autoAnalysisdata.setGpsHeight(carEvent.getGpsHeight());
			autoAnalysisdata.setBoxUp(carEvent.getBoxUp());
			autoAnalysisdata.setBoxEmpty(carEvent.getBoxEmpty());
			autoAnalysisdata.setBoxClose(carEvent.getBoxClose());
			autoAnalysisdata.setInsertTime(new Date());
			autoAnalysisdata.setVioStarttime(carEvent.getReceiveDatetime());
			
			if (carEvent.getEventType().intValue() == 31) {
				autoAnalysisdata.setEventType(Constant.beidouExceptionType);
				autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
			} else if (carEvent.getEventType().intValue() == 63) {
				autoAnalysisdata.setEventType(Constant.boxExceptionType);
				autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
			} else if (carEvent.getEventType().intValue() == 64) {
				autoAnalysisdata.setEventType(Constant.heavyEmptyType);
				autoAnalysisdataMapper.insertSelective(autoAnalysisdata);
			}
		}
	}
	
}
